#define PY_SSIZE_T_CLEAN


#include "python_init.h"
#include "pytype_traits.h"
#include "Slot.hpp"
#include "Signal.hpp"

int py_slot_proxy(void*);

int main()
{
	app_initialize_python();

	Signal<> signal;
	signal.bind(py_slot_proxy);
	int a = 1;
	signal.emit(&a);

	app_finalize_python();
	return 0;
}

int py_slot_proxy(void* p)
{
    const char module_name[] = "app";
	int* a = (int*)p;
    typedef std::map<std::string, int> map_t;
	map_t dict;
	dict["a"] = *a;

    PyObject* py_params = pytype_traits_t<map_t>::pyobj_from_cppobj(dict);
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;

    pName = PyUnicode_DecodeFSDefault(module_name);
    pModule = PyImport_Import(pName);
    Py_XDECREF(pName);
    if(pModule != NULL)
    {
        pFunc = PyObject_GetAttrString(pModule, "router");
        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(1);
            PyTuple_SetItem(pArgs, 0, py_params);
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_XDECREF(pArgs);
            Py_XDECREF(pValue);

            //pytype_traits_t<map_t>::pyobj_to_cppobj(py_params, dict);
            long result=0;
            if (pytype_traits_t<long>::pyobj_to_cppobj(PyDict_GetItemString(py_params, "result"), result) == 0) {
            	pytype_traits_t<long>::pyobj_to_cppobj(PyDict_GetItemString(py_params, "data"), result);
                printf("data = %d\n",  result);
            }

        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", "router");
        }
        Py_XDECREF(pFunc);
        Py_XDECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load '%s'\n", module_name);
    }
    Py_XDECREF(py_params);

	return 0;
}
